import os
import sys
import time
import uuid
import xml.etree.ElementTree as ET
from DrissionPage import ChromiumPage, ChromiumOptions
from bs4 import BeautifulSoup

# 获取脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))


class Worker:
    def __init__(self, username='1003206180', password='1003206180', url_file_path='C:\\Users\\admin\Desktop\\500.txt'):
        self.config_path = F'{script_dir}\Config\config.xml'
        self.username = username
        self.password = password
        self.url_file_path = url_file_path  # 要查询的URL文本地址
        self.unique_id = str(uuid.uuid4()).replace('-', '')
        self.save_path = F'{script_dir}\下载_{self.unique_id}'

    def read_chrmoe_path(self):
        """
        读取chrome配置文件路径
        :return:
        """
        chrome_path = ''
        try:
            # 打开文件并读取内容
            with open(F'{script_dir}/Config/chrome_path.txt', 'r', encoding='utf-8') as file:
                lines = file.readlines()
            # 遍历每一行，找到包含'chrome.exe'的行
            for line in lines:
                if 'chrome.exe' in line:
                    chrome_path = line.strip()
                    print(f'可执行文件路径读取成功：{chrome_path}')
                    break
            return chrome_path
        except:
            print('未找到chrome_path可执行文件路径')

    def chrom_page(self):
        """
        打开一个chrome浏览器
        :return: page对象
        """
        chrome_path = self.read_chrmoe_path()
        try:
            path = fr'{chrome_path}'
            co = ChromiumOptions().auto_port()
            co.set_browser_path(path)
            page = ChromiumPage(co)
            # 设置窗口最大化
            page.set.window.max()
            # 访问网页
            page.get('https://www.link114.cn/')
            return page
        except Exception as e:
            print(f'Chrome启动失败：{e}，请检查chrome_path路径是否正确。')
            return False

    def login(self, page, username, password):
        try:
            page.ele("x://span[@class='floatright member_info']//a").click()  # 点击登录
            page.ele('@name=username').input(username)  # 账号
            time.sleep(2)
            page.ele('@name=passwd').input(password)  # 密码
            time.sleep(2)
            page.ele("x://*[@id='do_submit']").click()  # 点击登录按钮
            time.sleep(2)
            page.ele('x:/html/body/div[2]/a').click()  # 登录成功后进入主页
            time.sleep(2)
            return page
        except Exception as e:
            print(f'登录出现异常:{e}')
            return page

    def split_txt_file(self, file_path, lines_per_file=500):
        """
        分割TXT到文件夹中
        :param file_path: 需要分割的TXT文件路径
        :param lines_per_file: 每个TXT中分割多少条数据
        :return: 包含完整路径的文件名列表
        """
        # 创建保存新文件的目录
        output_dir = f'{script_dir}\split_txt_files_{lines_per_file}'
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        with open(file_path, 'r', encoding='utf-8') as file:
            lines = file.readlines()
            # 计算需要创建的新文件数量
        num_files = (len(lines) + lines_per_file - 1) // lines_per_file
        # 分割文件并保存
        file_names = []  # 初始化一个空列表来保存文件名
        for i in range(num_files):
            start_idx = i * lines_per_file
            end_idx = min((i + 1) * lines_per_file, len(lines))
            file_contents = lines[start_idx:end_idx]
            # 构建新文件的名称
            file_name = f'split_file_{i + 1}.txt'
            file_path_new = os.path.join(output_dir, file_name)
            with open(file_path_new, 'w', encoding='utf-8') as new_file:
                new_file.writelines(file_contents)
                # 将文件名添加到列表中
            file_names.append(file_name)
            # 输出中文并返回包含新文件名的列表
        print(f"分割完成。在'{output_dir}'目录中创建了 {num_files} 个新的txt文件。")
        return [f'{output_dir}/' + name for name in file_names]  # 返回包含完整路径的文件名列表

    def read_txt_file(self, file_path):
        """
        读取TXT中的内容
        :param file_path: TXT文件路径
        :return: 文件内容
        """
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()
            return content
        except FileNotFoundError:
            print(f"文件未找到：{file_path}")
            return None
        except Exception as e:
            print(f"读取文件时发生错误：{e}")
            return None

    def load_config(self, xml_file):
        """
        解析XML配置文件，并返回元素的操作配置列表。
        :param xml_file: str，XML配置文件的路径。
        :return: list，包含所有元素的操作配置，每个配置为一个三元组 (name, xpath, enabled)。
        """
        tree = ET.parse(xml_file)  # 解析XML文件并获取根元素
        root = tree.getroot()
        actions = []  # 初始化一个空列表，用于存储所有元素的操作配置
        for elem in root.findall('element'):  # 遍历XML文件中所有的<element>元素
            name = elem.find('name').text  # 名称
            xpath = elem.find('xpath').text  # XPATH
            # 获取<element>中的<enabled>标签内容，判断是否启用点击操作
            enabled = elem.find('enabled').text.lower() == 'true'  # 将其转换为布尔值，'true' (不区分大小写) 为True，其余为False
            actions.append((name, xpath, enabled))  # 将名称、XPath路径和是否启用点击操作存储为一个元组，并添加到actions列表中
        # 返回包含所有元素配置的列表
        return actions

    def click_tijiao(self, page, content, config_file):
        page.ele('x://*[@id="ip_websites"]').input(content, clear=True)  # 输入域名
        time.sleep(2)
        page.ele('x:/html/body/div[3]/div[1]/p[1]/span').click()  # 全选
        time.sleep(1)
        page.ele('x:/html/body/div[3]/div[1]/p[1]/span').click()  # 全选
        time.sleep(1)

        # 加载XML配置文件
        actions = self.load_config(config_file)
        # 遍历配置文件中的动作并执行
        for name, xpath, enabled in actions:
            if enabled:
                print(f"点击 {name} ({xpath})")  # 输出到控制台，方便调试
                element = page.ele(f'x:{xpath}')
                element.click()
                time.sleep(0.5)  # 根据需要添加延时

        page.ele('x://*[@id="tj"]/a').click()  # 点击提交按钮

        # 等待加载完成的循环
        while True:
            tbody_html = page.ele('x://*[@id="result_table"]/tbody').html
            soup = BeautifulSoup(tbody_html, "html.parser")
            all_tr = soup.find('tbody').find_all('tr')[1:]  # 排除表头
            loading_gif_found = False
            for tr in all_tr:
                for td in tr.find_all('td'):
                    if '/template/images/loading.gif' in str(td):
                        loading_gif_found = True
                        break
                if loading_gif_found:
                    break
            if not loading_gif_found:
                break
            time.sleep(3)

    def click_recheck(self, page):
        """
        重查失败
        :param page:
        :return:
        """
        page.ele('x://*[@id="float_box"]/div[2]/a/span').click()  # 点击提交按钮
        time.sleep(3)

        tbody_html = page.ele('x://*[@id="result_table"]/tbody').html
        if '重查' in tbody_html or '失败' in tbody_html:
            while True:
                tbody_html = page.ele('x://*[@id="result_table"]/tbody').html
                soup = BeautifulSoup(tbody_html, "html.parser")
                all_tr = soup.find('tbody').find_all('tr')[1:]  # 排除表头
                # 检查所有td是否都不包含'/template/images/loading.gif'
                loading_gif_found = False
                for tr in all_tr:
                    for td in tr.find_all('td'):
                        if '/template/images/loading.gif' in str(td):
                            loading_gif_found = True
                            break  # 如果找到，则跳出内层循环
                    if loading_gif_found:
                        break  # 如果当前tr中有td包含指定字符串，则跳出外层循环
                    else:
                        pass
                # 检查是否所有td都不包含'/template/images/loading.gif'
                if not loading_gif_found:
                    break  # 如果所有td都不包含该字符串，则退出循环
                time.sleep(3)

    def click_save_path(self, page, txt_name):
        page.ele('x://*[@id="selectall"]/span').click()  # 点击全选
        time.sleep(2)
        mission = page.ele('x://*[@id="float_box"]/div[3]/a/span').click.to_download(save_path=self.save_path,
                                                                                     rename=f'{txt_name}')  # 点击导出
        mission.wait()
        time.sleep(5)

    def main(self):
        page = self.chrom_page()
        is_Login = True  # 代表需要登陆
        if is_Login:
            page = self.login(page, self.username, self.password)
            lines_per_file = 2000
        else:
            lines_per_file = 500
        txt_lists = self.split_txt_file(self.url_file_path, lines_per_file)
        for txt_path in txt_lists:
            content = self.read_txt_file(txt_path)
            print(f'正在查询:{txt_path}')
            self.click_tijiao(page, content, self.config_path)
            print(f'{txt_path}查询完成')
            print(f'正在重查:{txt_path}')
            self.click_recheck(page)
            print(f'{txt_path}重查完成')
            print(f'准备导出:{txt_path}')
            txt_name = os.path.basename(txt_path)
            self.click_save_path(page, txt_name)
            print(f'{txt_path}导出完成')


if __name__ == '__main__':
    worker = Worker()
    worker.main()
